package com.yvon.maple.service.base.controller;

import cn.hutool.core.lang.Assert;
import com.yvon.boot.common.result.ResponseData;
import com.yvon.boot.mybatis.page.ListData;
import com.yvon.boot.mybatis.search.PageQuery;
import com.yvon.maple.cloud.api.base.dto.FileInfoDTO;
import com.yvon.maple.cloud.web.data.AbstractController;
import com.yvon.maple.service.base.entity.FileInfo;
import com.yvon.maple.service.base.service.FileInfoService;
import com.yvon.maple.service.base.util.Base64FileUtil;
import com.yvon.maple.service.base.vo.FileInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 文件信息 controller
 *
 * @author : Yvon
 * @version : 1.0
 * @since : 2020-11-03
 */
@RestController
@RequestMapping(value = "/files", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Api(value = "文件管理", tags = "文件服务 - 文件管理API")
public class FileInfoController extends AbstractController<FileInfo, FileInfoDTO, FileInfoVO, FileInfoService> {

    /**
     * 上传单个文件
     *
     * @param file     文件
     * @return : ResponseEntity<FileInfoDTO>
     * @author : Yvon / 2020-11-04
     */
    @PostMapping(value = "/single", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "上传单个文件", response = FileInfoDTO.class,
            notes = "上传单个文件")
    public ResponseData<FileInfoDTO> add(@RequestPart("file") MultipartFile file){
        checkFile(file);
        FileInfo fileInfo = getService().putFile(file);
        return success(entityToDto(fileInfo));
    }

    @PostMapping(value = "/video", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "上传视频文件", response = FileInfoDTO.class,
            notes = "上传视频文件")
    public ResponseData<FileInfoDTO> addVideo(@RequestPart("file") MultipartFile file){
        checkFile(file);
        FileInfo fileInfo = getService().putVideo(file);
        return success(entityToDto(fileInfo));
    }

    /**
     * 上传多个文件
     *
     * @param files    文件
     * @return : ResponseEntity<List<FileInfoDTO>>
     * @author : Yvon / 2020-11-04
     */
    @PostMapping(value = "/multiple", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "上传多个文件", notes = "上传多个文件", response = FileInfoDTO.class)
    public ResponseData<List<FileInfoDTO>> add(@RequestParam("files") List<MultipartFile> files){
        files.forEach(this::checkFile);
        List<FileInfo> fileInfos = getService().putFiles(files);
        return success((entityToDto(fileInfos)));
    }


    /**
     * 上传base64文件
     *
     * @param base64Str    base64字符串
     * @return : ResponseEntity<List<FileInfoDTO>>
     * @author : Yvon / 2020-11-04
     */
    @PostMapping(value = "/base64", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "上传base64文件", notes = "上传base64文件", response = FileInfoDTO.class)
    public ResponseData<FileInfoDTO> add(@RequestParam(value = "base64") String base64Str){
        MultipartFile file = Base64FileUtil.base64ToMultipart(base64Str);
        checkFile(file);
        FileInfo fileInfo = getService().putFile(file);
        return success(entityToDto(fileInfo));
    }



    /**
     * 根据编号查询url
     *
     * @param id 编号
     * @return : ResponseEntity<Set<String>>
     * @author : Yvon / 2020-11-04
     */
    @GetMapping(value = "/url/id/{id}")
    @ApiOperation(value = "根据编号查询url", notes = "根据编号查询url API", response = String.class)
    public ResponseData<String> getUrlById(@PathVariable(value = "id") Long id) {
        return success(getService().getTempUrl(id, null));
    }

    /**
     * 根据文件编号下载
     *
     * @param id       编号
     * @param response 响应
     * @author : Yvon / 2020-11-04
     */
    @GetMapping(value = "/download/{id}")
    @ApiOperation(value = "根据文件编号下载", notes = "根据文件编号下载")
    public void download(@PathVariable("id") Long id, HttpServletResponse response){
        FileInfo fileInfo = getService().getById(id);
        Assert.notNull(fileInfo, "文件信息不存在或存储方式错误!");
        try(final InputStream inputStream = getService().getFileStream(fileInfo)) {
            response.setContentType(fileInfo.getContentType());
            response.setContentLengthLong(fileInfo.getFileSize());
            //防止中文乱码
            String fileName = URLEncoder.encode(fileInfo.getFileOriName(), "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName);
            ServletOutputStream outputStream = response.getOutputStream();
            IOUtils.copy(inputStream, outputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @GetMapping(value = "/dp")
    @ApiOperation(value = "根据文件编号下载", notes = "根据文件编号下载")
    public void download1(HttpServletResponse response){
        try {
            // 以流的形式下载文件。
            InputStream fileInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\yufeng\\Downloads\\流程图 (22).jpg"));
            response.setContentType("image/jpeg");
            IOUtils.copy(fileInputStream, response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 通过编号文件信息
     *
     * @param id 编号
     * @return : ResponseEntity<FileInfoDTO>
     * @author : Yvon / 2020-11-04
     */
    @GetMapping(value = "/id/{id}")
    @ApiOperation(value = "通过编号文件信息", notes = "通过编号文件信息API", response = FileInfoDTO.class)
    public ResponseData<FileInfoDTO> getById(@PathVariable("id") Long id){
        FileInfo fileInfo = getService().getById(id);
        FileInfoDTO fileInfoDTO = new FileInfoDTO();
        BeanUtils.copyProperties(fileInfo, fileInfoDTO);
        return success((fileInfoDTO));
    }

    /**
     * 删除文件
     *
     * @param id id
     * @return : ResponseData<Boolean>
     * @author : Yvon / 2020-11-04
     */
    @DeleteMapping("/id/{id}")
    @ApiOperation(value = "删除文件", response = Boolean.class,
            notes = "删除文件")
    public ResponseData<Boolean> deleteById(@PathVariable("id") Long id){
        return success(getService().removeById(id));
    }

    /**
     * 批量删除文件
     *
     * @param ids id
     * @return : ResponseData<Boolean>
     * @author : Yvon / 2020-11-04
     */
    @DeleteMapping
    @ApiOperation(value = "批量删除文件", response = Boolean.class, notes = "批量删除文件")
    public ResponseData<Boolean> deleteByIds(@RequestBody List<Long> ids){
        return success(getService().removeByIds(ids));
    }


    /**
     * 分页查询.
     *
     * @param pageQuery the param
     * @return the response data
     * @author : Yvon / 2020-02-17
     */
    @GetMapping("/page")
    @ApiOperation(value = "分页查询", notes = "分页查询")
    public ResponseData<ListData<FileInfoDTO>> page(PageQuery pageQuery) {
        ListData page = getService().page(pageQuery);
        List list = page.getList();
        page.setList(entityToDto(list));
        return success(page);
    }

    @GetMapping("/info")
    @ApiOperation(value = "通过业务关联查询文件信息", notes = "通过业务关联查询文件信息")
    public ResponseData<List<FileInfoDTO>> fileInfo(@RequestParam(value = "businessKeys") @NotNull Set<String> businessKeys, @RequestParam(value = "hours", required = false) Integer hours) {
        List<FileInfo> fileInfoList = getService().getFileInfo(businessKeys, hours);
        return success(entityToDto(fileInfoList));
    }

    @GetMapping("/key/tempUrl")
    @ApiOperation(value = "获取临时访问路径(通过业务key)", notes = "获取临时访问路径(通过业务key)")
    public ResponseData<List<String>> getTempUrlByBusiness(@RequestParam(value = "businessKeys") @NotNull Set<String> businessKeys, @RequestParam(value = "hours", required = false) Integer hours) {
        return success(getService().getTempUrlByBusiness(businessKeys, hours));
    }

    @GetMapping("/id/tempUrl")
    @ApiOperation(value = "获取临时访问路径(通过文件id)", notes = "获取临时访问路径(通过文件id)")
    public ResponseData<List<String>> tempUrlByFileIds(@RequestParam(value = "fileIds") @NotNull Set<Long> fileIds, @RequestParam(value = "hours", required = false) Integer hours) {
        return success(getService().getTempUrl(fileIds, hours));
    }

    @GetMapping("/map/tempUrl")
    @ApiOperation(value = "批量", hidden = true)
    public ResponseData<Map<String, List<String>>> mapTempUrl(@RequestParam(value = "businessKeys") @NotNull Set<String> businessKeys, @RequestParam(value = "hours", required = false) Integer hours) {
        Map<String, List<String>> map = getService().tempUrlMap(businessKeys, hours);
        return success(map);
    }





    /**
     * 检查文件
     *
     * @param file 文件
     * @author : Yvon / 2020-11-04
     */
    private void checkFile(MultipartFile file) {
        if (Objects.isNull(file) || file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空!");
        }
    }

}
